home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / c / GAPLib.lha / GAPLib / wizards / Conjurer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-25  |  43.1 KB  |  1,942 lines

  1. /*
  2.  * The GAP Conjurer (C)1999 Peter Bengtsson
  3.  *
  4.  * Note: This source is one big hack, so do not expect too much structure
  5.  *       or readability from it.
  6.  *
  7.  * History:
  8.  *
  9.  *        22/4-1999: v1.0
  10.  *            First version
  11.  *
  12.  *        23/4-1999: v1.1
  13.  *            Consistently use 0 for exit in menues.
  14.  *            Changed menu named to reflect their position in the hierarchy.
  15.  *
  16.  *        24/4-1999: v1.2
  17.  *            Added setting of some rudimentary genome data.
  18.  *
  19.  *        25/4-1999: v1.3
  20.  *            Fixed potential problem with special characters in project name.
  21.  *
  22.  *        26/4-1999:    v1.4
  23.  *            Rewrote data filter to enable using more comples templates.
  24.  *            Fixed a bug in the code generation for multiple source files.
  25.  *            Fixed a bug which initialized the bitstring length to 0 as default.
  26.  *
  27.  *        7/5-1999:    v1.5
  28.  *            Added default extension ".spell" to save filename.
  29.  *
  30.  *        18/5-1999:    v1.6
  31.  *            Implemented help in the menu() function.
  32.  *            Started writing help texts.
  33.  *
  34.  *        21/5-1999:    v1.7
  35.  *            Added support for indexed reports.
  36.  *            Improved the help user-interface.
  37.  *            Added more help texts.
  38.  *            Added external fitness function loading.
  39.  *
  40.  *        24/5-1999:    v1.8
  41.  *            Fixed a bug in the BitMatrix template file.
  42.  *            Fixed a potential NULL-reference in menu().
  43.  *            Fixed save/load to handle external fitness functions.
  44.  *            Added 1 line of missing initialization code.
  45.  *
  46.  *        25/5-1999:    v1.9
  47.  *            Added a missing ',' in the comment level helptext array.
  48.  *            Wrote more helptexts again.
  49.  *
  50.  *
  51.  */
  52.  
  53.  
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #include <ctype.h>
  57. #include <string.h>
  58. #include <time.h>
  59. #include <sys/stat.h>
  60. #include <errno.h>
  61.  
  62. #include "data/bs_c.c"
  63. #include "data/bm_c.c"
  64. #include "data/bv_c.c"
  65. #include "data/sk_c.c"
  66. #include "data/report_h.c"
  67. #include "data/report_c.c"
  68. #include "data/mk.c"
  69.  
  70.  
  71. /* Undefine this to make this program strictly conforming to ISO-C. */
  72.  
  73. #define    IMPURE
  74.  
  75.  
  76. #define    _STRM(x)    #x
  77. #define    STRM(x)    _STRM(x)
  78.  
  79. const char * const __v__="$VER: GAP-Conjurer 1.9 (25.5.99) ©1999 Peter Bengtsson";
  80.  
  81. #define    CLEAR    "\x1b[H\x1b[J"
  82.  
  83. #define    SPECIALCHARS    " !@#$%^&*()\\/+[];:?><~'`"
  84.  
  85. #define    TF(x)    ((x)?"TRUE":"FALSE")
  86.  
  87. #define    DIR_SEPARATOR    '/'
  88.  
  89. #ifdef    AMIGA
  90. #define    CURRENT_DIR    ""
  91. #else
  92. #define    CURRENT_DIR    "."
  93. #endif
  94.  
  95. #define    Rnd(a)    (rand()%a)
  96. #define    InitRand(a)    srand((unsigned int)a)
  97.  
  98. #define    YES    'Y'
  99. #define    NO        'N'
  100.  
  101. #define    DEFY    "[Y/n]"
  102. #define    DEFN    "[y/N]"
  103.  
  104. #define    MN_IGN    0
  105. #define    MN_STR    1
  106. #define    MN_INT    2
  107. #define    MN_BOL    3
  108. #define    MN_EXT    -1
  109.  
  110. #define    WIZFLG_PLOT        (1<<0)
  111. #define    WIZFLG_PSPLOT    (1<<1)
  112. #define    WIZFLG_MPASS    (1<<2)
  113. #define    WIZFLG_INDXD    (1<<3)
  114.  
  115. #define    DEF_GENERATIONS    32
  116.  
  117. #define    DEF_BRVLEN    3
  118.  
  119. #define    DEF_NAME    "Manhattan"
  120.  
  121. #define    NUM_DEFNAMES    11
  122.  
  123. char    *includes[] = {
  124.     "stdio",
  125.     "stdlib",
  126.     "string",
  127.     "math",
  128.     "time",
  129.     "GAP",
  130.     NULL
  131. };
  132.  
  133. char    *FitnessMenu[] = {
  134.     "Empty function",
  135.     "From file",
  136.     0
  137. };
  138.  
  139. char    *SelectNames[] = {
  140.     "Double Random",
  141.     "Fitness Proportionate",
  142.     "Sigma Scaled",
  143.     "Tournament",
  144.     "Inorder",
  145.     "Boltzmann",
  146.     "Universal",
  147.     NULL
  148. };
  149.  
  150. char *SelectHelp[] = {
  151.     "Select a random individual but not the fittest one, then select an\nindividual with higher fitness than the first.",
  152.     "Individuals are selected in a linear fashion according to their fitness.",
  153.     "Fitness proportionate with scaling based on the standard deviation.",
  154.     "The two fittest of 4 random individuals are selected.",
  155.     "The fittest individual is selected with all others.",
  156.     "Selection with variable preassure. See documentation for more info.",
  157.     "Normalized fitness proportionate selection.",
  158.     NULL
  159. };
  160.  
  161. char    *RepDefs[] = {
  162.     "AVERAGE",
  163.     "MEDIAN",
  164.     "TYPECOUNT",
  165.     "MAX",
  166.     "MIN",
  167.     "STDDEV"
  168. };
  169.  
  170. char *RepNames[] = {
  171.     "Average",
  172.     "Median",
  173.     "Typecount",
  174.     "Maximum",
  175.     "Minimum",
  176.     "Standard Deviation"
  177. };
  178.  
  179. char *RepExts[] = {
  180.     "avg",
  181.     "med",
  182.     "typ",
  183.     "max",
  184.     "min",
  185.     "dev"
  186. };
  187.  
  188. char    *SelectDefs[] = {
  189.     "DRANDOM",
  190.     "FITPROP",
  191.     "SIGMA",
  192.     "TOURNAMENT",
  193.     "INORDER",
  194.     "TEMPERATURE",
  195.     "UNIVERSAL"
  196. };
  197.  
  198. char    *CrossoverNames[] = {
  199.     "Singlepoint",
  200.     "Multipoint",
  201.     "Custom",
  202.     NULL
  203. };
  204.  
  205. char    *InitNames[] = {
  206.     "Random init",
  207.     "Zero init",
  208.     "Custom init",
  209.     NULL
  210. };
  211.  
  212. char    *CLNames[] = {
  213.     "None",
  214.     "Normal",
  215.     "Verbose",
  216.     "Irritating",
  217.     "Overwhelming",
  218.     NULL
  219. };
  220.  
  221. char *CLHelp[] = {
  222.     "No comments at all.",
  223.     "Only the most important and informative comments.",
  224.     "Comments on most code passages.",
  225.     "Lots of comments, even some useless ones.",
  226.     "Parts of the function reference inlined as comments.",
  227.     0
  228. };
  229.  
  230. char    **CLMenu = CLNames;
  231.  
  232. #define    PTYPE_Bitstring    0
  233. #define    PTYPE_Bitmatrix    1
  234. #define    PTYPE_BRVector        2
  235. #define    PTYPE_Custom        3
  236.  
  237. char    *GenomeNames[] = {
  238.     "Bitstring",
  239.     "Bitmatrix",
  240.     "Bounded double vector",
  241.     "Custom",
  242.     NULL
  243. };
  244.  
  245. char    *GenomeHelp[] = {
  246.     "Simple bitstring",
  247.     "Bitmatrix with 2-dimensional crossover.",
  248.     "Vector of floating point values constrained to specified ranges.\nCrossover is either on a per element basis or numerical.",
  249.     "This option requires you to write all code yourself.\nOnly empty functions are provided.",
  250.     0
  251. };
  252.  
  253. char    **GenomeMenu = GenomeNames;
  254.  
  255. char    *DefNames[] = {
  256.     "Tourist",
  257.     "Hacker",
  258.     "Gnome",
  259.     "Borg",
  260.     "Bug",
  261.     "Zool",
  262.     "Ghost",
  263.     "Hobbit",
  264.     "Haddock",
  265.     "Dinosaur",
  266.     "Polyphant",
  267.     NULL
  268. };
  269.  
  270. struct VDisp {
  271.     int    Type;
  272.     long    Val;
  273. };
  274.  
  275. char    *Menu1[] = {
  276.     "Project parameters",
  277.     "Population parameters",
  278.     "Make project",
  279.     "Save configuration",
  280.     "Load configuration",
  281.     "Quit",
  282.     NULL
  283. };
  284.  
  285. struct VDisp MainVals[] = {
  286.     {MN_IGN,0},
  287.     {MN_IGN,0},
  288.     {MN_IGN,0},
  289.     {MN_IGN,0},
  290.     {MN_IGN,0},
  291.     {MN_EXT,0}
  292. };
  293.  
  294. char    *PrParms[] = {
  295.     "Project name",
  296.     "No. of populations",
  297.     "Comment level",
  298.     "Multiple sourcefiles",
  299.     "GNUPlot script",
  300.     "PostScript plots",
  301.     "Exit",
  302.     NULL
  303. };
  304.  
  305. char *PrHelp[] = {
  306.     "The name of this project and also the basename for the generated\nsource files.",
  307.     "Number of populations in this project.",
  308.     "Selects how heavily commented the generated code should be.",
  309.     "Put the fitness function(s) in a separate source file.",
  310.     "Automatically plot data with GNUPlot after running a session.\n(Does not work with indexed reports yet.)",
  311.     "Make postscript plots of the generated data after a run.\n(Does not work with indexed reports yet.)",
  312.     "Exit the menu.",
  313.     0
  314. };
  315.  
  316. struct VDisp PrVals[] = {
  317.     {MN_STR,0},
  318.     {MN_INT,0},
  319.     {MN_STR,0},
  320.     {MN_BOL,0},
  321.     {MN_BOL,0},
  322.     {MN_BOL,0},
  323.     {MN_EXT,0}
  324. };
  325.  
  326. char    *PoParms[] = {
  327.     "Change name",
  328.     "Change size",
  329.     "Genome type",
  330.     "Environment parameters",
  331.     "Report parameters",
  332.     "Fitness function",
  333.     "Exit",
  334.     NULL
  335. };
  336.  
  337. struct VDisp PoVals[] = {
  338.     {MN_STR,0},
  339.     {MN_INT,0},
  340.     {MN_STR,0},
  341.     {MN_IGN,0},
  342.     {MN_IGN,0},
  343.     {MN_STR,0},
  344.     {MN_EXT,0}
  345. };
  346.  
  347. char    *Flags[] = {
  348.     "Init type",
  349.     "Selection method",
  350.     "Crossover",
  351.     "Crowding",
  352.     "Mutation",
  353.     "Pre-mutate",
  354.     "Elitism",
  355.     "Dump worst",
  356.     "Init dumped",
  357.     "Newbies",
  358.     "Erase best",
  359.     "Make stats",
  360.     "Exit",
  361.     NULL
  362. };
  363.  
  364. char    *FlagsHelp[] = {
  365.     "How to initialize the individuals in a newly created population.",
  366.     "What type of selection to use.",
  367.     "How to perform crossover of two individuals.",
  368.     "With crowding enabled each new individual replaces that individual\nin the old population that it resembles the most. This aids\ndiversity and makes for overlapping generations.",
  369.     "Determines if mutation is to take place.",
  370.     "Mutate after evaluation, this is to simulate mutation occuring\nin mature individuals. This means that the fitness of an\nindividual might not reflect the actual fitness of its genome.",
  371.     "Copy a number of the best individuals instead of generating a whole\nnew population. ",
  372.     "Remove the worst individuals from the population before generating the\nnext one. This increases the chances of the fittest individuals.",
  373.     "If \"dump worst\" above is greater than zero, re-initialize the worst\nindividuals instead of removing them.",
  374.     "Randomly replace individuals with new ones.",
  375.     "If \"newbies\" above is greater than zero, replace the fittest individuals\nwith newly generated ones. This is to keep the population\naverage down eg. when co-evolving populations.",
  376.     "Generate statistics for eg. making report files.",
  377.     "Exit the menu",
  378.     0
  379. };
  380.  
  381. char    *FlagTags[] = {
  382.     "EVL_Evaluator",
  383.     "EVL_Select",
  384.     "EVL_Crosser",
  385.     "EVL_Crowding",
  386.     "EVL_Mutator",
  387.     "EVL_PreMutate",
  388.     "EVL_Elite",
  389.     "EVL_Dump",
  390.     "EVL_InitDumped",
  391.     "EVL_Newbies",
  392.     "EVL_EraseBest",
  393.     "EVL_Stats"
  394. };
  395.  
  396. struct VDisp FlagVals[] = {
  397.     {MN_STR,0},
  398.     {MN_STR,0},
  399.     {MN_STR,0},
  400.     {MN_BOL,0},
  401.     {MN_BOL,0},
  402.     {MN_BOL,0},
  403.     {MN_INT,0},
  404.     {MN_INT,0},
  405.     {MN_BOL,0},
  406.     {MN_INT,0},
  407.     {MN_BOL,0},
  408.     {MN_BOL,0},
  409.     {MN_EXT,0}
  410. };
  411.  
  412. char    *RFlagMenu[] = {
  413.     "Average",
  414.     "Median",
  415.     "Typecount",
  416.     "Max",
  417.     "Min",
  418.     "Standard Deviation",
  419.     "Toggle All",
  420.     "Runs to average",
  421.     "Indexed reports",
  422.     "Exit",
  423.     NULL
  424. };
  425.  
  426. char *RFlagHelp[] = {
  427.     "Report average fitness.",
  428.     "Report median fitness.",
  429.     "Report the number of occurances of the most common fitness.",
  430.     "Report the maximum fitness.",
  431.     "Report the minimum fitness.",
  432.     "Report the standard deviation of the population fitness values.",
  433.     "Toggle the above flags.",
  434.     "Generate average values of N runs. Note that all reports are saved\nafter being generated in this case.",
  435.     "Do not overwrite old report files but instead generate new names\nfor each run of the program.",
  436.     "Exit the menu",
  437.     0
  438. };
  439.  
  440. struct VDisp RFlagVals[] = {
  441.     {MN_BOL,0},
  442.     {MN_BOL,0},
  443.     {MN_BOL,0},
  444.     {MN_BOL,0},
  445.     {MN_BOL,0},
  446.     {MN_BOL,0},
  447.     {MN_IGN,0},
  448.     {MN_INT,0},
  449.     {MN_BOL,0},
  450.     {MN_EXT,0}
  451. };
  452.  
  453. struct NPop {
  454.     char    *Name;
  455.     int    Size;
  456.     int    Type;
  457.     int    Flags[12];
  458.     int    RFlags[6];
  459.     int    GData;
  460.     char    *FFile;
  461. };
  462.  
  463. struct {
  464.     char    *Name;
  465.     int    NumPops,CLevel;
  466.     struct NPop *Pops;
  467.     int rep,sep,flags,pass;
  468. } Project;
  469.  
  470. char    *MOTD;
  471.  
  472. int    mcount(char **);
  473.  
  474. int    menu(char *,char **,struct VDisp *,char **);
  475. int    msg(char *);
  476. int    int_query(char *,int);
  477. char *str_query(char *,char *);
  478. int    bool_query(char *,int);
  479. void    save_template(char *);
  480. void    load_template(char *);
  481. void    save_pop(FILE *,struct NPop);
  482. void    load_pop(FILE *,int);
  483. void    create_project(char *);
  484. char *addpart(char *,char *);
  485. void filtdump(FILE *,unsigned char *,int);
  486. int    file_write(char *);
  487. void filtdump2(FILE *,char *,int,int);
  488.  
  489.  
  490. int main(int cnt,char *arg[])
  491. {
  492. char    z,buf[255],buf2[64],*tmenu[16],*p;
  493. struct VDisp tvals[16];
  494. int    i,n;
  495.  
  496. InitRand(time(NULL));
  497.  
  498. Project.Name=malloc(strlen(DEF_NAME)+1);
  499. strcpy(Project.Name,DEF_NAME);
  500. Project.NumPops=1;
  501. Project.Pops = NULL;
  502. Project.CLevel = 1;
  503. PrVals[0].Val = (long)Project.Name;
  504. PrVals[1].Val = 1;
  505. PrVals[2].Val = (long)CLNames[1];
  506. PrVals[3].Val = 0;
  507. Project.sep=0;
  508. Project.Pops = malloc(sizeof(struct NPop));
  509. memset(Project.Pops,0,sizeof(struct NPop));
  510. Project.Pops[0].Name = malloc(10);
  511. strcpy(Project.Pops[0].Name,"Polyphant");
  512. Project.Pops[0].Flags[4] = 1;    /* Do mutate */
  513. Project.Pops[0].Size = 20;
  514. Project.Pops[0].GData = 4;
  515. Project.Pops[0].FFile = 0;
  516. Project.flags=0;
  517. Project.pass=1;
  518.  
  519. MOTD = malloc(1024);
  520.  
  521. strcpy(MOTD,"Welcome.");
  522.  
  523. switch(cnt) {
  524. case    1:
  525.     z=msg(CLEAR "\nWelcome! This is the GAP Conjurer.\n\nConjure a skeleton? " DEFY " : ");
  526. break;
  527.  
  528. case    2:
  529.     if(strcmp(arg[1],"-h") || strcmp(arg[1],"--help")) {
  530.         fprintf(stderr,"%s [Template] [Dest. Dir]\n",arg[0]);
  531.         goto tixE;
  532.     }
  533.     load_template(arg[1]);
  534.     z = 1;
  535. break;
  536.  
  537. case    3:
  538.     load_template(arg[1]);
  539.     create_project(arg[2]);
  540.     goto tixE;
  541. break;
  542.  
  543. default:
  544.     fprintf(stderr,"%s [Template] [Dest. Dir]\n",arg[0]);
  545.     goto tixE;
  546. }
  547.  
  548. if(toupper(z)!=NO) {
  549.     do {
  550.         i=menu("Main Menu",Menu1,MainVals,0);
  551.         switch(i) {
  552.         case    1:
  553.             do {
  554.                 i = menu("Main/Project parameters",PrParms,PrVals,PrHelp);
  555.                 switch(i) {
  556.                 case    1:    /* Project Name */
  557.                     free(Project.Name);
  558.                     Project.Name = str_query("Project name [" DEF_NAME "] ?",DEF_NAME);
  559.                     PrVals[0].Val = (long)Project.Name;
  560.                     for(i=0;i!=strlen(SPECIALCHARS);i++) {
  561.                         if(strchr(Project.Name,SPECIALCHARS[i])!=NULL) {
  562.                             msg("The useage of special characters is STRONGLY discouraged. [ENTER]");
  563.                         }
  564.                     }
  565.                     sprintf(MOTD,"Project name is now %s.",Project.Name);
  566.                 break;
  567.  
  568.                 case    2:    /* # of pops */
  569.                     i = int_query("How many populations in project [1] ?",1);
  570.                     if(i>0) {
  571.                         for(n=0;n!=Project.NumPops;n++) {
  572.                             if(Project.Pops[n].Name!=NULL) {
  573.                                 free(Project.Pops[n].Name);
  574.                             }
  575.                         }
  576.                         Project.NumPops = i;
  577.                         PrVals[1].Val = Project.NumPops;
  578.                         if(Project.Pops!=NULL) free(Project.Pops);
  579.                         Project.Pops = malloc(Project.NumPops*sizeof(struct NPop));
  580.                         memset(Project.Pops,0,Project.NumPops*sizeof(struct NPop));
  581.                         n=Rnd(NUM_DEFNAMES);
  582.                         for(i=0;i!=Project.NumPops;i++) {
  583.                             sprintf(buf,"Name for population #%d [%s]? :",i,DefNames[(i+n)%NUM_DEFNAMES]);
  584.                             Project.Pops[i].Name = str_query(buf,DefNames[(i+n)%NUM_DEFNAMES]);
  585.                             Project.Pops[i].Flags[4] = 1;    /* Do mutate */
  586.                             Project.Pops[i].Size = 20;
  587.                             Project.Pops[i].GData = 4;
  588.                             Project.Pops[i].FFile = 0;
  589.                         }
  590.                     }
  591.                     sprintf(MOTD,"%d populations created.",Project.NumPops);
  592.                 break;
  593.  
  594.                 case    3:    /* Comment level */
  595.                     Project.CLevel = menu("Main/Project/Comment level",CLMenu,NULL,CLHelp)-1;
  596.                     PrVals[2].Val = (long)CLNames[Project.CLevel];
  597.                     sprintf(MOTD,"Comment level set to %s.",CLNames[Project.CLevel]);
  598.                 break;
  599.  
  600.                 case    4:
  601.                     Project.sep^=1;
  602.                     PrVals[3].Val^=1;
  603.                 break;
  604.  
  605.                 case    5:
  606.                     Project.flags ^= WIZFLG_PLOT;
  607.                     PrVals[4].Val = Project.flags&WIZFLG_PLOT;
  608.                 break;
  609.  
  610.                 case    6:
  611.                     Project.flags ^= WIZFLG_PSPLOT;
  612.                     PrVals[5].Val = Project.flags&WIZFLG_PSPLOT;
  613.                 break;
  614.  
  615.                 }
  616.             } while(i!=mcount(PrParms));
  617.             i=1;
  618.         break;
  619.  
  620.         case    2:    /* Pop params */
  621.             if(Project.NumPops>0) {
  622.                 do {
  623.                     if(Project.NumPops>1) {
  624.                         for(i=0;i!=Project.NumPops;i++) {
  625.                             tmenu[i] = Project.Pops[i].Name;
  626.                             tvals[i].Type = MN_IGN;
  627.                         }
  628.                         tvals[i].Type = MN_EXT;
  629.                         tmenu[i] = "Exit";
  630.                         tmenu[i+1] = 0;
  631.                         n = menu("Main/Select Population",tmenu,tvals,0)-1;
  632.                         if(n==(mcount(tmenu)-1)) {
  633.                             break;
  634.                         }
  635.                     } else {
  636.                         n = 0;
  637.                     }
  638.                     PoVals[0].Val = (long)Project.Pops[n].Name;
  639.                     PoVals[1].Val = Project.Pops[n].Size;
  640.                     PoVals[2].Val = (long)GenomeNames[Project.Pops[n].Type];
  641.                     PoVals[5].Val = (long)((Project.Pops[n].FFile==0)?"Empty":Project.Pops[n].FFile);
  642.                     do {
  643.                         sprintf(buf,"Main/Pop/Parameters for %s population",Project.Pops[n].Name);
  644.                         i = menu(buf,PoParms,PoVals,0);
  645.                         switch(i) {
  646.                         case    1:    /* Name */
  647.                             strcpy(buf,Project.Pops[n].Name);
  648.                             free(Project.Pops[n].Name);
  649.                             Project.Pops[n].Name = str_query("New name: ",buf);
  650.                             PoVals[0].Val = (long)Project.Pops[n].Name;
  651.                             sprintf(MOTD,"Name changed to %s.",Project.Pops[n].Name);
  652.                         break;
  653.  
  654.                         case    2:    /* Size */
  655.                             sprintf(buf,"New population size [%d]? : ",Project.Pops[n].Size);
  656.                             Project.Pops[n].Size = int_query(buf,Project.Pops[n].Size);
  657.                             PoVals[1].Val = Project.Pops[n].Size;
  658.                             sprintf(MOTD,"Size changed to %d.",Project.Pops[n].Size);
  659.                         break;
  660.  
  661.                         case    3: /* Genome type */
  662.                             i = menu("Main/Pop/Param/Select genome type",GenomeMenu,NULL,GenomeHelp);
  663.                             Project.Pops[n].Type = i-1;
  664.                             switch(Project.Pops[n].Type) {
  665.                             case    PTYPE_Bitstring:
  666.                                 Project.Pops[n].GData = int_query("Byte length of bitstring [4]? ",4);
  667.                             break;
  668.  
  669.                             case    PTYPE_BRVector:
  670.                                 Project.Pops[n].GData = int_query("Elements in vector? [" STRM(DEF_BRVLEN) "]? ",DEF_BRVLEN);
  671.                             break;
  672.  
  673.                             case    PTYPE_Bitmatrix:
  674.                                 Project.Pops[n].GData = int_query("Height of matrix [8]? ",8);
  675.                                 Project.Pops[n].GData |= int_query("Width of matrix [8]? ",8)<<16;
  676.                             break;
  677.  
  678.                             default:
  679.                                 ;
  680.                             }
  681.                             PoVals[2].Val=(long)GenomeNames[i-1];
  682.                             sprintf(MOTD,"%s genome type set to %s.",Project.Pops[n].Name,GenomeNames[i-1]);
  683.                         break;
  684.  
  685.                         case    4: /* Flags */
  686.                             sprintf(buf,"Main/Pop/Param/Flags for %s population",Project.Pops[n].Name);
  687.                             do {
  688.                                 FlagVals[0].Val = (long)InitNames[Project.Pops[n].Flags[0]];
  689.                                 FlagVals[1].Val = (long)SelectNames[Project.Pops[n].Flags[1]];
  690.                                 FlagVals[2].Val = (long)CrossoverNames[Project.Pops[n].Flags[2]];
  691.                                 FlagVals[3].Val = Project.Pops[n].Flags[3];
  692.                                 FlagVals[4].Val = Project.Pops[n].Flags[4];
  693.                                 FlagVals[5].Val = Project.Pops[n].Flags[5];
  694.                                 FlagVals[6].Val = Project.Pops[n].Flags[6];
  695.                                 FlagVals[7].Val = Project.Pops[n].Flags[7];
  696.                                 FlagVals[8].Val = Project.Pops[n].Flags[8];
  697.                                 FlagVals[9].Val = Project.Pops[n].Flags[9];
  698.                                 FlagVals[10].Val = Project.Pops[n].Flags[10];
  699.                                 FlagVals[11].Val = Project.Pops[n].Flags[11];
  700.                                 FlagVals[12].Val = Project.Pops[n].Flags[12];
  701.                                 i = menu(buf,Flags,FlagVals,FlagsHelp);
  702.                                 switch(i) {
  703.                                 case    1:    /* Init */
  704.                                     Project.Pops[n].Flags[0] = menu("Main/Pop/Param/Flags/Select initialization type",InitNames,NULL,0)-1;
  705.                                 break;
  706.                                 case    2:    /* Select */
  707.                                     Project.Pops[n].Flags[1] = menu("Main/Pop/Param/Flags/Select selection type",SelectNames,NULL,SelectHelp)-1;
  708.                                 break;
  709.                                 case    3:    /* Crossover */
  710.                                     Project.Pops[n].Flags[2] = menu("Main/Pop/Param/Flags/Select crossover type",CrossoverNames,NULL,0)-1;
  711.                                 break;
  712.                                 case    4:    /* Crowding */
  713.                                     Project.Pops[n].Flags[3] ^= 1;
  714.                                  break;
  715.                                 case    5:    /* Mutation */
  716.                                     Project.Pops[n].Flags[4] ^= 1;
  717.                                 break;
  718.                                 case    6:    /* Pre-Mutation */
  719.                                     Project.Pops[n].Flags[5] ^= 1;
  720.                                 break;
  721.                                 case    7:    /* Elitism */
  722.                                     Project.Pops[n].Flags[6] = int_query("Elite individuals [0]?",0);
  723.                                 break;
  724.                                 case    8:    /* Dump Worst */
  725.                                     Project.Pops[n].Flags[7] = int_query("Individuals to remove [0]?",0);
  726.                                 break;
  727.                                 case    9:    /* Init Dumped */
  728.                                     Project.Pops[n].Flags[8] ^= 1;
  729.                                 break;
  730.                                 case    10:    /* Newbies */
  731.                                     Project.Pops[n].Flags[9] = int_query("Individuals to regenerate [0]?",0);
  732.                                 break;
  733.                                 case    11:    /* Erase Best */
  734.                                     Project.Pops[n].Flags[10] ^= 1;
  735.                                 break;
  736.                                 case    12:    /* Make Stats */
  737.                                     Project.Pops[n].Flags[11] ^= 1;
  738.                                 break;
  739.                                 }
  740.                             } while(i!=mcount(Flags));
  741.                         break;
  742.  
  743.                         case    5: /* Report */
  744.                             sprintf(buf,"Main/Pop/Param/Report generation for %s population",Project.Pops[n].Name);
  745.                             do {
  746.                                 for(i=0;i!=6;i++) {
  747.                                     RFlagVals[i].Val = Project.Pops[n].RFlags[i];
  748.                                 }
  749.                                 RFlagVals[7].Val = Project.pass;
  750.                                 i = menu(buf,RFlagMenu,RFlagVals,RFlagHelp);
  751.                                 switch(i) {
  752.                                 case    1:
  753.                                 case    2:
  754.                                 case    3:
  755.                                 case    4:
  756.                                 case    5:
  757.                                 case    6:
  758.                                     Project.Pops[n].RFlags[i-1]^=1;
  759.                                 break;
  760.                                 case    7:
  761.                                     for(i=0;i!=6;i++) {
  762.                                         Project.Pops[n].RFlags[i]^=1;
  763.                                     }
  764.                                 break;
  765.                                 case    8:
  766.                                     Project.flags &= ~WIZFLG_MPASS;
  767.                                     i = int_query("Take average of how many passes [1] ?",1);
  768.                                     if(i>1) {
  769.                                         Project.flags |= WIZFLG_MPASS;
  770.                                     } else {
  771.                                         i = 1;
  772.                                     }
  773.                                     RFlagVals[7].Val = i;
  774.                                     Project.pass = i;
  775.                                 break;
  776.                                 case    9:
  777.                                     Project.flags ^= WIZFLG_INDXD;
  778.                                     RFlagVals[8].Val = (Project.flags&WIZFLG_INDXD);
  779.                                 break;
  780.                                 }
  781.                             } while(i!=mcount(RFlagMenu));
  782.                             for(i=0;i!=6;i++) {
  783.                                 if(Project.Pops[n].RFlags[i]!=0 && Project.Pops[n].Flags[11]==0) {
  784.                                     Project.Pops[n].Flags[11] = 1;
  785.                                     strcpy(MOTD,"Auto-enabled statistics.");
  786.                                     break;
  787.                                 }
  788.                             }
  789.                             i=0;
  790.                         break;
  791.                         case    6:    /* Fitness */
  792.                             i = menu("Main/Population/Select fitness function.",FitnessMenu,0,0);
  793.                             if(Project.Pops[n].FFile!=0) {
  794.                                 free(Project.Pops[n].FFile);
  795.                             }
  796.                             switch(i) {
  797.                             case    1:
  798.                                 PoVals[5].Val = (int)"Empty";
  799.                                 Project.Pops[n].FFile=0;
  800.                             break;
  801.                             case    2:
  802.                                 Project.Pops[n].FFile = str_query("Fitness template file [fitness.t]? :","fitness.t");
  803.                                 PoVals[5].Val = (int)Project.Pops[n].FFile;
  804.                             break;
  805.                             default:
  806.                                 msg("Danger Will Robinson, cosmic storm approaching.");
  807.                             }
  808.                         break;
  809.                         }
  810.                     } while(i!=mcount(PoParms));
  811.                 } while(Project.NumPops>1);
  812.             } else {
  813.                 strcpy(MOTD,"Too few populations.");
  814.                 msg("Please set number of populations >= 1. [ENTER]");
  815.             }
  816.             i=2;
  817.         break;
  818.  
  819.         case    3:    /* Make project */
  820.             sprintf(buf,"Destination directory? [%s]? : ",CURRENT_DIR);
  821.             p = str_query(buf,CURRENT_DIR);
  822.             create_project(p);
  823.             free(p);
  824.         break;
  825.  
  826.         case    4:    /* Save */
  827.             sprintf(buf2,"%s.spell",Project.Name);
  828.             sprintf(buf,"Save as [%s]? : ",buf2);
  829.             p = str_query(buf,buf2);
  830.             save_template(p);
  831.             free(p);
  832.         break;
  833.  
  834.         case    5:    /* Load */
  835.             p = str_query("Load project [" DEF_NAME ".spell]? : ",DEF_NAME ".spell");
  836.             load_template(p);
  837.             free(p);
  838.         break;
  839.  
  840.         case    6: /* Quit */
  841.             if(!bool_query("Really quit " DEFN "? :",NO)) {
  842.                 i=0;
  843.             }
  844.         break;
  845.         }    /* switch() */
  846.     } while(i!=mcount(Menu1));
  847. } else {
  848.     printf("Too bad.\n");
  849. }
  850.  
  851. tixE:;
  852.  
  853. if(Project.Pops!=NULL) {
  854.     for(i=0;i!=Project.NumPops;i++) {
  855.         if(Project.Pops[i].Name!=NULL) {
  856.             free(Project.Pops[i].Name);
  857.         }
  858.     }
  859.     free(Project.Pops);
  860. }
  861.  
  862. if(Project.Name!=NULL) {
  863.     free(Project.Name);
  864. }
  865.  
  866. if(MOTD) {
  867.     free(MOTD);
  868. }
  869.  
  870. return(0);
  871. }
  872.  
  873. int menu(char *title,char **items,struct VDisp *vs,char **help)
  874. {
  875. int i,n;
  876. int x=0;
  877. char buf[255];
  878. static int xh=0;
  879.  
  880. do {
  881.     printf(CLEAR "\n \x1b[4m%s\x1b[0m\n\n",title);
  882.     i=0;
  883.     while(items[i]!=NULL) {
  884.         printf("  %2d) %-24s",(vs!=0 && vs[i].Type==MN_EXT)?0:i+1,items[i]);
  885.         if(vs!=NULL) {
  886.             switch(vs[i].Type) {
  887.             case    MN_IGN:
  888.             break;
  889.  
  890.             case    MN_EXT:
  891.                 x=i;
  892.             break;
  893.  
  894.             case    MN_INT:
  895.                 printf("(%ld)",vs[i].Val);
  896.             break;
  897.  
  898.             case    MN_STR:
  899.                 if(vs[i].Val!=0) {
  900.                     printf("(%s)",(char *)vs[i].Val);
  901.                 }
  902.             break;
  903.  
  904.             case    MN_BOL:
  905.                 printf("(%s)",(vs[i].Val)?"Yes":"No");
  906.             break;
  907.  
  908.             default:
  909.                 fprintf(stderr,"menu: BUG!\n");
  910.             }
  911.         }
  912.         printf("\n");
  913.         i++;
  914.     }
  915.  
  916.     if(help!=0) {
  917.         printf("\n   H)elp available.");
  918.     }
  919.  
  920.     if(xh==1) {
  921.         printf("\n  eX)it help.");
  922.     }
  923.  
  924.     printf("\n==> ");
  925.  
  926.     if(MOTD!=NULL) {
  927.         printf("\n\nLast Message: %s\n\x1b[3A\x1b[4C",MOTD);
  928.     }
  929.  
  930.     fflush(stdout);
  931.  
  932.     fgets(buf,255,stdin);
  933.  
  934.     if(xh==1 && buf[0]=='x') {
  935.         return(0);
  936.     }
  937.  
  938.     if(help!=0 && (buf[0]=='h' || buf[0]=='H')) {
  939.         xh=1;
  940.         do {
  941.             n = menu("Display help on which item?",items,0,0)-1;
  942.             if(n>=0) {
  943.                 printf(help[n]);
  944.                 msg("\n[ENTER]");
  945.             }
  946.         } while(n!=-1);
  947.         xh=0;
  948.     }
  949.  
  950.     n = atol(buf);
  951.  
  952.     if(n==0 && buf[0]=='0' && x!=0) {
  953.         n = x+1;
  954.     }
  955.  
  956. } while(n<1 || n>i);
  957.  
  958. printf("\x1b[J");fflush(stdout);
  959.  
  960. return(n);
  961. }
  962.  
  963. int msg(char *m)
  964. {
  965. char    buf[255];
  966. fflush(stdin);
  967. printf(m);
  968. fflush(stdout);
  969. fgets(buf,255,stdin);
  970. return((int)buf[0]);
  971. }
  972.  
  973. int int_query(char *m,int def)
  974. {
  975. int    i;
  976. char    buf[255],*p;
  977. fflush(stdin);
  978. printf(m);
  979. fflush(stdout);
  980. fgets(buf,255,stdin);
  981. i = strtol(buf,&p,0);
  982. if(p==buf) {
  983.     i = def;
  984. }
  985. return(i);
  986. }
  987.  
  988. char *str_query(char *m,char *def)
  989. {
  990. char    buf[255],*p;
  991. printf(m);
  992. fflush(stdout);
  993. fgets(buf,255,stdin);
  994. if(buf[0]=='\n') {
  995.     if(def!=NULL) {
  996.         strcpy(buf,def);
  997.     } else {
  998.         return(NULL);
  999.     }
  1000. }
  1001. if(strchr(buf,'\n')!=NULL) {
  1002.     strchr(buf,'\n')[0]=0;
  1003. }
  1004. p = malloc(strlen(buf)+1);
  1005. strcpy(p,buf);
  1006. return(p);
  1007. }
  1008.  
  1009. int mcount(char **s)
  1010. {
  1011. int i;
  1012. i = -1;
  1013. while(s[++i]!=0);
  1014. return(i);
  1015. }
  1016.  
  1017. int bool_query(char *s,int d)
  1018. {
  1019. int v;
  1020. v = msg(s);
  1021. switch(d) {
  1022.  
  1023. case    YES:
  1024.     if(toupper(v)!=NO) {
  1025.         v=1;
  1026.     }
  1027. break;
  1028.  
  1029. case    NO:
  1030.     if(toupper(v)!=YES) {
  1031.         v=0;
  1032.     }
  1033. break;
  1034.  
  1035. default:
  1036.     fprintf(stderr,"bool_query: BUG!\n");
  1037. }
  1038.  
  1039. return(v);
  1040. }
  1041.  
  1042. void save_template(char *fname)
  1043. {
  1044. FILE *fp;
  1045. struct stat State;
  1046. int    r,i;
  1047.  
  1048. r=stat(fname,&State);
  1049.  
  1050. if(r==0) {
  1051.     if(bool_query("File exists, overwrite? [y/N] : ",NO)) {
  1052.         errno=ENOENT;
  1053.     } else {
  1054.         return;
  1055.     }
  1056. }
  1057.  
  1058. strcpy(MOTD,"Error while saving project template.");
  1059.  
  1060. if(errno==ENOENT) {
  1061.     fp = fopen(fname,"wb");
  1062.     if(fp!=NULL) {
  1063.         fprintf(fp,"This file is a product of the Frobozz Magic File Company.\n\n");
  1064.         fprintf(fp,"Project: %s\n",Project.Name);
  1065.         fprintf(fp,"Populations: %d\n",Project.NumPops);
  1066.         fprintf(fp,"CommentLevel: %d\n",Project.CLevel);
  1067.         fprintf(fp,"Multisource: %d\n",Project.sep);
  1068.         fprintf(fp,"Storyline: %d\n",Project.flags);
  1069.         fprintf(fp,"Passcount: %d\n\n",Project.pass);
  1070.         for(i=0;i!=Project.NumPops;i++) {
  1071.             save_pop(fp,Project.Pops[i]);
  1072.         }
  1073.         strcpy(MOTD,"Project template saved.");
  1074.         fclose(fp);
  1075.     } else {
  1076.         msg("save_template: General forseen non-fatal error occured. [ENTER]");
  1077.     }
  1078. } else {
  1079.     msg("save_template: General forseen non-fatal error occured. [ENTER]");
  1080. }
  1081. return;
  1082. }
  1083.  
  1084. void save_pop(FILE *fp,struct NPop pop)
  1085. {
  1086. int i;
  1087.  
  1088. fprintf(fp,"And now, the %s\n",pop.Name);
  1089. fprintf(fp,"\t%d,%d,",pop.Size,pop.Type);
  1090. for(i=0;i!=12;i++) {
  1091.     fprintf(fp,"%d,",pop.Flags[i]);
  1092. }
  1093. for(i=0;i!=6;i++) {
  1094.     fprintf(fp,"%d,",pop.RFlags[i]);
  1095. }
  1096. fprintf(fp,"%d,",pop.GData);
  1097. fprintf(fp,"\"%s\",",(pop.FFile!=0)?pop.FFile:"");
  1098. fprintf(fp,"*\n\n");
  1099. }
  1100.  
  1101. void load_template(char *fname)
  1102. {
  1103. FILE *fp;
  1104. struct stat State;
  1105. int    r,i;
  1106. char    buf[255];
  1107.  
  1108. r=stat(fname,&State);
  1109.  
  1110. if(r==0) {
  1111.     fp = fopen(fname,"rb");
  1112.     if(fp==NULL) {
  1113.         strcpy(MOTD,"Unable to read template.");
  1114.         msg("load_template: Irritating error, fopen() failed. [ENTER]");
  1115.         return;
  1116.     }
  1117.     fgets(buf,255,fp);
  1118.     if(!strcmp(buf,"This file is a product of the Frobozz Magic File Company.\n")) {
  1119.  
  1120.         if(Project.Pops!=NULL) {
  1121.             for(i=0;i!=Project.NumPops;i++) {
  1122.                 if(Project.Pops[i].Name!=NULL) {
  1123.                     free(Project.Pops[i].Name);
  1124.                 }
  1125.             }
  1126.             free(Project.Pops);
  1127.         }
  1128.  
  1129.         if(Project.Name!=NULL) {
  1130.             free(Project.Name);
  1131.         }
  1132.  
  1133.         while(fgets(buf,255,fp),buf[0]=='\n');
  1134.  
  1135.         strchr(buf,'\n')[0]=0;
  1136.         Project.Name = malloc(strlen(buf)-8);
  1137.         strcpy(Project.Name,&buf[9]);
  1138.  
  1139.         while(fgets(buf,255,fp),buf[0]=='\n');
  1140.         Project.NumPops = strtol(&buf[13],NULL,0);
  1141.  
  1142.         while(fgets(buf,255,fp),buf[0]=='\n');
  1143.         Project.CLevel = strtol(&buf[14],NULL,0);
  1144.  
  1145.         while(fgets(buf,255,fp),buf[0]=='\n');
  1146.         Project.sep = strtol(&buf[13],NULL,0);
  1147.  
  1148.         while(fgets(buf,255,fp),buf[0]=='\n');
  1149.         Project.flags = strtol(&buf[11],NULL,0);
  1150.  
  1151.         while(fgets(buf,255,fp),buf[0]=='\n');
  1152.         Project.pass = strtol(&buf[11],NULL,0);
  1153.  
  1154.         Project.Pops = malloc(Project.NumPops*sizeof(struct NPop));
  1155.  
  1156.         for(i=0;i!=Project.NumPops;i++) {
  1157.             load_pop(fp,i);
  1158.         }
  1159.  
  1160.         PrVals[0].Val = (long)Project.Name;
  1161.         PrVals[1].Val = Project.NumPops;
  1162.         PrVals[2].Val = (long)CLNames[Project.CLevel];
  1163.         PrVals[3].Val = Project.sep;
  1164.         PrVals[4].Val = Project.flags&WIZFLG_PLOT;
  1165.         PrVals[5].Val = Project.flags&WIZFLG_PSPLOT;
  1166.         sprintf(MOTD,"Template for the %s project loaded.",Project.Name);
  1167.     } else {
  1168.         strcpy(MOTD,"Unrecognized fileformat.");
  1169.         msg("Unrecognized fileformat. [ENTER]");
  1170.     }
  1171.     fclose(fp);
  1172. } else {
  1173.     strcpy(MOTD,"Unable to examine template.");
  1174.     msg("load_template: File inaccessible. [ENTER]");
  1175. }
  1176. return;
  1177.  
  1178. }
  1179.  
  1180. void load_pop(FILE *fp,int n)
  1181. {
  1182. int i;
  1183. char buf[255],*p1;
  1184.  
  1185. while(fgets(buf,255,fp),strncmp(buf,"And now, the ",12));
  1186. strchr(buf,'\n')[0]=0;
  1187.  
  1188. Project.Pops[n].Name = malloc(strlen(buf)-11);
  1189. strcpy(Project.Pops[n].Name,&buf[13]);
  1190.  
  1191. fscanf(fp,"\t%d,%d,",&Project.Pops[n].Size,&Project.Pops[n].Type);
  1192.  
  1193. for(i=0;i!=12;i++) {
  1194.     fscanf(fp,"%d,",&Project.Pops[n].Flags[i]);
  1195. }
  1196. for(i=0;i!=6;i++) {
  1197.     fscanf(fp,"%d,",&Project.Pops[n].RFlags[i]);
  1198. }
  1199. fscanf(fp,"%d,",&Project.Pops[n].GData);
  1200.  
  1201. if(Project.Pops[n].FFile!=0) {
  1202.     free(Project.Pops[n].FFile);
  1203. }
  1204.  
  1205. fgets(buf,255,fp);
  1206. p1 = strchr(buf,'"');
  1207. p1++;
  1208. strchr(p1,'"')[0]=0;
  1209. if(p1[0]!=0) {
  1210.     Project.Pops[n].FFile = malloc(strlen(p1)+1);
  1211.     strcpy(Project.Pops[n].FFile,p1);
  1212. } else {
  1213.     Project.Pops[n].FFile = 0;
  1214. }
  1215.  
  1216. return;
  1217. }
  1218.  
  1219. void    create_project(char *dstdir)
  1220. {
  1221. FILE    *fp,*sp,*hp;
  1222. char    *buf;
  1223. struct NPop *Pops;
  1224. struct stat State;
  1225. int r,rep;
  1226. int i,n;
  1227.  
  1228. buf = malloc(2048);
  1229.  
  1230. Pops = Project.Pops;
  1231. strcpy(buf,dstdir);
  1232. addpart(buf,Project.Name);
  1233. strcat(buf,".c");
  1234.  
  1235. r=stat(buf,&State);
  1236.  
  1237. if(r==0) {
  1238.     if(!bool_query("Project exists, overwrite? [y/N] :",NO)) {
  1239.         free(buf);
  1240.         return;
  1241.     }
  1242. }
  1243.  
  1244. rep=0;
  1245. for(i=0;i!=Project.NumPops;i++) {
  1246.     for(n=0;n!=6;n++) {
  1247.         rep |= Pops[i].RFlags[n];
  1248.     }
  1249. }
  1250.  
  1251. Project.rep = rep;
  1252.  
  1253. fp = fopen(buf,"wb");
  1254. if(Project.sep) {
  1255.     strcpy(buf,dstdir);
  1256.     addpart(buf,Project.Name);
  1257.     strcat(buf,"Fitness.c");
  1258.     sp = fopen(buf,"wb");
  1259.     strcpy(buf,dstdir);
  1260.     addpart(buf,Project.Name);
  1261.     strcat(buf,".h");
  1262.     hp = fopen(buf,"wb");
  1263. } else {
  1264.     sp = fp;
  1265.     hp = fp;
  1266. }
  1267.  
  1268. if(fp!=NULL && sp!=NULL) {
  1269.  
  1270.     switch(Project.CLevel) {
  1271.     case    1:
  1272.         fprintf(fp,"/*\n *\t%s.c\n *\tCreated by the GAP Conjurer.\n *\n */\n\n",Project.Name);
  1273.     break;
  1274.  
  1275.     case    2:
  1276.     case    3:
  1277.         fprintf(fp,"/*\n *\t%s.c\n *\tCreated by the GAP Conjurer.\n *\n *\n * Populations:\n",Project.Name);
  1278.         for(i=0;i!=Project.NumPops;i++) {
  1279.             fprintf(fp," *\t%s population.\n",Pops[i].Name);
  1280.         }
  1281.         fprintf(fp," */\n\n");
  1282.     break;
  1283.  
  1284.     case    4:
  1285.         fprintf(fp,"/*\n *\t%s.c\n *\tCreated by the GAP Conjurer.\n *\n *\n * Populations:\n",Project.Name);
  1286.         for(i=0;i!=Project.NumPops;i++) {
  1287.             fprintf(fp," *\t%s population. (%d individuals initially)\n",Pops[i].Name,Pops[i].Size);
  1288.             fprintf(fp," *\t\t %-20s(%s)\n",Flags[0],InitNames[Pops[i].Flags[0]]);
  1289.             fprintf(fp," *\t\t %-20s(%s)\n",Flags[1],SelectNames[Pops[i].Flags[1]]);
  1290.             fprintf(fp," *\t\t %-20s(%s)\n",Flags[2],CrossoverNames[Pops[i].Flags[2]]);
  1291.             fprintf(fp," *\t\t %-20s(%s)\n",Flags[3],(Pops[i].Flags[3])?"Yes":"No");
  1292.             fprintf(fp," *\t\t %-20s(%s)\n",Flags[4],(Pops[i].Flags[4])?"Yes":"No");
  1293.             fprintf(fp," *\t\t %-20s(%s)\n",Flags[5],(Pops[i].Flags[5])?"Yes":"No");
  1294.             fprintf(fp," *\t\t %-20s(%d)\n",Flags[6],Pops[i].Flags[6]);
  1295.             fprintf(fp," *\t\t %-20s(%d)\n",Flags[7],Pops[i].Flags[7]);
  1296.             fprintf(fp," *\t\t %-20s(%s)\n",Flags[8],(Pops[i].Flags[8])?"Yes":"No");
  1297.             fprintf(fp," *\t\t %-20s(%d)\n",Flags[9],Pops[i].Flags[9]);
  1298.             fprintf(fp," *\t\t %-20s(%s)\n",Flags[10],(Pops[i].Flags[10])?"Yes":"No");
  1299.             fprintf(fp," *\t\t %-20s(%s)\n",Flags[11],(Pops[i].Flags[11])?"Yes":"No");
  1300.             fprintf(fp," *\n");
  1301.         }
  1302.         fprintf(fp," */\n\n");
  1303.     break;
  1304.  
  1305.     default:
  1306.         ;
  1307.     }
  1308.  
  1309.  
  1310.     if(Project.CLevel>2) {
  1311.         fprintf(fp,"/* Includes follow */\n");
  1312.     }
  1313.  
  1314.  
  1315.     i = 0;
  1316.     while(includes[i]!=NULL) {
  1317.         fprintf(fp,"#include <%s.h>\n",includes[i++]);
  1318.     }
  1319.  
  1320.     if(rep!=0) {
  1321.         fprintf(fp,"#include \"report.h\"\n");
  1322.     }
  1323.  
  1324.     if(Project.sep!=0) {
  1325.         fprintf(fp,"#include \"%s.h\"\n",Project.Name);
  1326.     }
  1327.  
  1328.     fprintf(hp,"\n%s",(Project.CLevel>0)?"/* Population defines. */\n\n":"");
  1329.  
  1330.     buf[0]=0;
  1331.     for(i=0;i!=Project.NumPops;i++) {
  1332.         if(Project.CLevel>1) {
  1333.             sprintf(buf,"\t/* Initial size of %s population. */",Pops[i].Name);
  1334.         }
  1335.         fprintf(hp,"#define\t%sSIZE\t%d%s\n",Pops[i].Name,Pops[i].Size,buf);
  1336.     }
  1337.  
  1338.     fprintf(hp,"\n%s",(Project.CLevel>0)?"/* Population structures. */\n\n":"");
  1339.  
  1340.     for(i=0;i!=Project.NumPops;i++) {
  1341.  
  1342.         fprintf(hp,"\n/*===== %s =====*/\n\n",Pops[i].Name);
  1343.  
  1344.         fprintf(hp,"#%s\tZINIT%d\n",(Pops[i].Flags[0]==1)?"define":"undef",i);
  1345.         fprintf(hp,"#%s\tMPCROSS%d\n\n",(Pops[i].Flags[2]==1)?"define":"undef",i);
  1346.  
  1347.         switch(Pops[i].Type) {
  1348.         case    PTYPE_Bitstring:
  1349.             fprintf(hp,"#define\tSIZE%d\t%d%s\n\n",i,Pops[i].GData,(Project.CLevel>1)?"\t/* _BYTE_ length of bitstring. */":"");
  1350.         break;
  1351.  
  1352.         case    PTYPE_Bitmatrix:
  1353.             fprintf(hp,"#define\tWIDTH%d\t%d\n",i,Pops[i].GData>>16);
  1354.             fprintf(hp,"#define\tHEIGHT%d\t%d\n",i,Pops[i].GData&0xffff);
  1355.             fprintf(hp,"#define\tXBYTES%d\t((WIDTH%d+7)>>3)\n\n",i,i);
  1356.         break;
  1357.  
  1358.         case    PTYPE_BRVector:
  1359.             fprintf(hp,"#define\tVLENGTH%d\t%d\n\nstatic double Constraints%d[VLENGTH%d][2] = {%s\n",i,Pops[i].GData,i,i,(Project.CLevel>0)?" /* Constraint ranges. */":"");
  1360.             for(n=0;n<(Pops[i].GData-1);n++) {
  1361.                 fprintf(hp,"   {-1.0,1.0},%s\n",(Project.CLevel>2)?"\t/* This comment is here just to irritate you. */":"");
  1362.             }
  1363.             fprintf(hp,"   {-1.0,1.0}\n};\n\n");
  1364.         break;
  1365.  
  1366.         case    PTYPE_Custom:
  1367.         break;
  1368.  
  1369.         default:
  1370.             fprintf(hp,"/* Error in population type. */\n\n");
  1371.         }
  1372.  
  1373.         fprintf(hp,"struct %s {\n",Pops[i].Name);
  1374.         switch(Pops[i].Type) {
  1375.         case    PTYPE_Bitstring:
  1376.             fprintf(hp,"   unsigned char Data[SIZE%d];\n",i);
  1377.         break;
  1378.  
  1379.         case    PTYPE_Bitmatrix:
  1380.             fprintf(hp,"   unsigned char matrix[HEIGHT%d][XBYTES%d];\n   int x,y,xb;\n",i,i);
  1381.         break;
  1382.  
  1383.         case    PTYPE_BRVector:
  1384.             fprintf(hp,"   double\tv[%d];\n",DEF_BRVLEN);
  1385.         break;
  1386.  
  1387.         case    PTYPE_Custom:
  1388.             if(Project.CLevel>0) {
  1389.                 fprintf(hp,"   /* Define custom data for %s here. */\n",Pops[i].Name);
  1390.             }
  1391.         break;
  1392.  
  1393.         default:
  1394.             fprintf(hp,"/* Error in population type. */\n");
  1395.         }
  1396.         fprintf(hp,"};\n\n");
  1397.     }
  1398.  
  1399.     if(Project.CLevel>0) {
  1400.         fprintf(hp,"/* Function prototypes follow. */\n\n");
  1401.     }
  1402.  
  1403.     if(Project.CLevel>1) {
  1404.         fprintf(hp,"/* Fitness functions. */\n\n");
  1405.     }
  1406.  
  1407.     for(i=0;i!=Project.NumPops;i++) {
  1408.         fprintf(hp,"%sdouble %sFitness(struct %s *);\n",(Project.sep!=0)?"extern ":"",Pops[i].Name,Pops[i].Name);
  1409.     }
  1410.  
  1411.     fprintf(fp,"\n");
  1412.     if(Project.CLevel>1) {
  1413.         fprintf(hp,"/* Other functions. */\n\n");
  1414.     }
  1415.  
  1416.     for(i=0;i!=Project.NumPops;i++) {
  1417.         fprintf(hp,"%svoid Init%s(struct %s *);\n",(Project.sep!=0)?"extern ":"",Pops[i].Name,Pops[i].Name);
  1418.         if(Pops[i].Flags[4]!=0) {
  1419.             fprintf(hp,"%svoid Mutate%s(struct %s *);\n",(Project.sep!=0)?"extern ":"",Pops[i].Name,Pops[i].Name);
  1420.         }
  1421.         fprintf(hp,"%svoid Cross%s(struct %s *,struct %s *);\n",(Project.sep!=0)?"extern ":"",Pops[i].Name,Pops[i].Name,Pops[i].Name);
  1422.         fprintf(hp,"%sdouble Compare%s(struct %s *,struct %s *,int);\n",(Project.sep!=0)?"extern ":"",Pops[i].Name,Pops[i].Name,Pops[i].Name);
  1423.         fprintf(hp,"%svoid Kill%s(struct %s *);\n",(Project.sep!=0)?"extern ":"",Pops[i].Name,Pops[i].Name);
  1424.         fprintf(hp,"\n");
  1425.     }
  1426.  
  1427. /* Create main() */
  1428.  
  1429.     if(Project.CLevel>0) {
  1430.         fprintf(fp,"/*=== Main program starts here. ===*/\n\n");
  1431.     }
  1432.  
  1433.     fprintf(fp,"int main(int cnt,char *arg[])\n{\nint\ti%s;\nint\tGenerations=10;\n",(Project.flags&WIZFLG_MPASS)?",n":"");
  1434.  
  1435.     for(i=0;i!=Project.NumPops;i++) {
  1436.         fprintf(fp,"struct Population *%sPop;\n",Pops[i].Name);
  1437.     }
  1438.  
  1439.     if(rep!=0) {
  1440.         for(i=0;i!=Project.NumPops;i++) {
  1441.             for(n=0;n!=6;n++) {
  1442.                 if(Pops[i].RFlags[n]!=0) {
  1443.                     fprintf(fp,"struct Report *%sRep;\n",Pops[i].Name);
  1444.                     break;
  1445.                 }
  1446.             }
  1447.         }
  1448.     }
  1449.  
  1450.     fprintf(fp,"\n");    
  1451.  
  1452.     for(i=0;i!=Project.NumPops;i++) {
  1453.         fprintf(fp,"struct TagItem %sInitTags[] = {\n"\
  1454.         "   {POP_Init,(IPTR)Init%s},\n"\
  1455.         "   {POP_Destruct,(IPTR)Kill%s},\n"\
  1456.         "   {POP_Cache,TRUE},\n"\
  1457.         "   {TAG_DONE,0L}\n};\n\n",Pops[i].Name,Pops[i].Name,Pops[i].Name);
  1458.     }
  1459.  
  1460.     for(i=0;i!=Project.NumPops;i++) {
  1461.         fprintf(fp,"struct TagItem %sEvolveTags[] = {",Pops[i].Name);
  1462.         for(n=0;n!=12;n++) {
  1463.             fprintf(fp,"\n   {%s,",FlagTags[n]);
  1464.             switch(n) {
  1465.             case    0:
  1466.                 fprintf(fp,"(IPTR)%sFitness},",Pops[i].Name);
  1467.             break;
  1468.             case    1:
  1469.                 fprintf(fp,"%s},",SelectDefs[Pops[i].Flags[n]]);
  1470.             break;
  1471.             case    2:
  1472.                 fprintf(fp,"(IPTR)Cross%s},",Pops[i].Name);
  1473.             break;
  1474.             case    3:
  1475.                 fprintf(fp,"%s},",TF(Pops[i].Flags[n]));
  1476.             break;
  1477.             case    4:
  1478.                 if(Pops[i].Flags[n]!=0) {
  1479.                     fprintf(fp,"(IPTR)Mutate%s},",Pops[i].Name);
  1480.                 } else {
  1481.                     fprintf(fp,"NULL},");
  1482.                 }
  1483.             break;
  1484.             case    5:
  1485.                 fprintf(fp,"%s},",TF(Pops[i].Flags[n]));
  1486.             break;
  1487.             case    6:
  1488.                 fprintf(fp,"%d},",Pops[i].Flags[n]);
  1489.             break;
  1490.             case    7:
  1491.                 fprintf(fp,"%d},",Pops[i].Flags[n]);
  1492.             break;
  1493.             case    8:
  1494.                 fprintf(fp,"%s},",TF(Pops[i].Flags[n]));
  1495.             break;
  1496.             case    9:
  1497.                 fprintf(fp,"%d},",Pops[i].Flags[n]);
  1498.             break;
  1499.             case    10:
  1500.                 fprintf(fp,"%s},",TF(Pops[i].Flags[n]));
  1501.             break;
  1502.             case    11:
  1503.                 fprintf(fp,"%s},",TF(Pops[i].Flags[n]));
  1504.             break;
  1505.             default:
  1506.                 fprintf(fp,"/* Tag creation error. */\n");
  1507.             }
  1508.         }
  1509.         fprintf(fp,"\n   {TAG_DONE,0L}\n};\n\n");
  1510.     }
  1511.  
  1512.     if(Project.flags&(WIZFLG_MPASS|WIZFLG_INDXD)) {
  1513.         fprintf(fp,"struct TagItem ReportTags[] = {\n");
  1514.         if(Project.flags&WIZFLG_MPASS) {
  1515.             fprintf(fp,"\t{REP_Generations,0},\n\t{REP_Multipass,TRUE},\n");
  1516.         }
  1517.         if(Project.flags&WIZFLG_INDXD) {
  1518.             fprintf(fp,"\t{REP_Indexed,TRUE},\n");
  1519.         }
  1520.         fprintf(fp,"\t{TAG_DONE,0L}\n};\n\n");
  1521.     }
  1522.  
  1523. /*    if(rep!=0 && (Project.flags&(WIZFLG_INDXD|WIZFLG_MPASS))==(WIZFLG_INDXD|WIZFLG_MPASS)) {
  1524.         fprintf(fp,"char NameBuf[64];\n\n");
  1525.     }*/
  1526.  
  1527.  
  1528.     fprintf(fp,"if(cnt>1) {\n   if(strcmp(arg[1],\"-h\")==0 || strcmp(arg[1],\"--help\")==0) {\n"\
  1529.         "      fprintf(stderr,\"Useage:\\n\\n%%s <Generations>\\n\\n\",arg[0]);\n      return(0);\n   }\n"\
  1530.         "   Generations = atoi(arg[1]);\n}\n\nif(Generations<1) {\n   Generations=10;\n}\n\n");
  1531.  
  1532.     fprintf(fp,"InitRand(time(NULL));\n\n");
  1533.  
  1534.     if(Project.flags&WIZFLG_MPASS) {
  1535.         fprintf(fp,"ReportTags[0].ti_Data = (IPTR)Generations;\n\n");
  1536.     }
  1537.  
  1538.     if(rep!=0) {
  1539.         for(i=0;i!=Project.NumPops;i++) {
  1540.             for(n=0;n!=6;n++) {
  1541.                 if(Pops[i].RFlags[n]!=0) {
  1542.                     fprintf(fp,"%sRep = MakeReport(\"%s\",%s);\n",Pops[i].Name,Pops[i].Name,(Project.flags&(WIZFLG_MPASS|WIZFLG_INDXD))?"ReportTags":"NULL");
  1543.                     break;
  1544.                 }
  1545.             }
  1546.         }
  1547.     }
  1548.  
  1549.     fprintf(fp,"\n");
  1550.  
  1551.     if(Project.flags&WIZFLG_MPASS) {
  1552.         fprintf(fp,"for(n=0;n!=%d;n++) {",Project.pass);
  1553.         if(Project.CLevel>2) {
  1554.             sprintf(buf,"\t/* Perform %d runs of this GA. */",Project.pass);
  1555.         }
  1556.         fprintf(fp,"\n\n");
  1557.     }
  1558.  
  1559.     for(i=0;i!=Project.NumPops;i++) {
  1560.         fprintf(fp,"%s%sPop = CreatePopulation(%sSIZE,sizeof(struct %s),%sInitTags);\n",(Project.flags&WIZFLG_MPASS)?"\t":"",Pops[i].Name,Pops[i].Name,Pops[i].Name,Pops[i].Name);
  1561.     }
  1562.  
  1563.     fprintf(fp,"\n%sif(",(Project.flags&WIZFLG_MPASS)?"\t":"");
  1564.     for(i=0;i!=(Project.NumPops-1);i++) {
  1565.         fprintf(fp,"%sPop!=NULL && ",Pops[i].Name);
  1566.     }
  1567.     fprintf(fp,"%sPop!=NULL) {\n",Pops[i].Name);
  1568.  
  1569.     fprintf(fp,"%s\tfor(i=0;i!=Generations;i++) {\n",(Project.flags&WIZFLG_MPASS)?"\t":"");
  1570.  
  1571.     for(i=0;i!=Project.NumPops;i++) {
  1572.         fprintf(fp,"%s\t\t%sPop = Evolve(%sPop,%sEvolveTags);\n",(Project.flags&WIZFLG_MPASS)?"\t":"",Pops[i].Name,Pops[i].Name,Pops[i].Name);
  1573.     }
  1574.  
  1575.     if(rep!=0) {
  1576.         fprintf(fp,"\n");
  1577.         for(i=0;i!=Project.NumPops;i++) {
  1578.             buf[0]=0;
  1579.             for(n=0;n!=6;n++) {
  1580.                 if(Pops[i].RFlags[n]!=0) {
  1581.                     strcat(buf,RepDefs[n]);
  1582.                     strcat(buf,"|");
  1583.                 }
  1584.             }
  1585.             if(buf[0]!=0) {
  1586.                 buf[strlen(buf)-1]=0;
  1587.                 fprintf(fp,"%s\t\tDoReport(%sRep,%sPop,%s);\n",(Project.flags&WIZFLG_MPASS)?"\t":"",Pops[i].Name,Pops[i].Name,buf);
  1588.             }
  1589.         }
  1590.     }
  1591.  
  1592.     fprintf(fp,"%s\t}\n%s}\n\n",(Project.flags&WIZFLG_MPASS)?"\t":"",(Project.flags&WIZFLG_MPASS)?"\t":"");
  1593.  
  1594.     for(i=0;i!=Project.NumPops;i++) {
  1595.         fprintf(fp,"%sif(%sPop!=NULL){ DeletePopulation(%sPop); }\n",(Project.flags&WIZFLG_MPASS)?"\t":"",Pops[i].Name,Pops[i].Name);
  1596.     }
  1597.  
  1598.     if(Project.flags&WIZFLG_MPASS) {
  1599.         fprintf(fp,"}\n");
  1600.     }
  1601.  
  1602.     fprintf(fp,"\n");
  1603.  
  1604.     if(rep!=0) {
  1605.         for(i=0;i!=Project.NumPops;i++) {
  1606.             for(n=0;n!=6;n++) {
  1607.                 if(Pops[i].RFlags[n]!=0) {
  1608.                     fprintf(fp,"if(%sRep!=NULL){ EndReport(%sRep); }\n",Pops[i].Name,Pops[i].Name);
  1609.                     break;
  1610.                 }
  1611.             }
  1612.         }
  1613.     }
  1614.  
  1615.     if(rep!=0) {
  1616.         if(Project.flags&WIZFLG_PSPLOT) {
  1617.             fprintf(fp,"\nsystem(\"gnuplot MakePS\");\n");
  1618.         }
  1619.         if(Project.flags&WIZFLG_PLOT) {
  1620.             fprintf(fp,"\nsystem(\"gnuplot ShowReport\");\n");
  1621.         }
  1622.     }
  1623.  
  1624.     fprintf(fp,"\nreturn(0);\n}\n\n");
  1625.  
  1626. /* == End of main() writing code == */
  1627.  
  1628. if(Project.sep!=0) {
  1629.     fprintf(sp,"#include <GAP.h>\n#include <math.h>\n#include \"%s.h\"\n\n",Project.Name);
  1630.     for(i=0;i!=Project.NumPops;i++) {
  1631.         fprintf(sp,"double %sFitness(struct %s *);\n",Pops[i].Name,Pops[i].Name);
  1632.     }
  1633.     fprintf(sp,"\n");
  1634. }
  1635.  
  1636. if(Project.CLevel>0) {
  1637.     fprintf(sp,"/*=== Fitness functions ===*/\n");
  1638.     if(Project.CLevel>2) {
  1639.         fprintf(sp,"/* Below here are the functions which define how\n * fit an individual is - commponly known as fitness functions.\n */\n\n");
  1640.     }
  1641. }
  1642.  
  1643. for(i=0;i!=Project.NumPops;i++) {
  1644.     if(Pops[i].FFile==0) {
  1645.         fprintf(sp,"double %sFitness(struct %s *Polly)\n{\ndouble fitness=0.0;\n",Pops[i].Name,Pops[i].Name);
  1646.         if(Project.CLevel>0) {
  1647.             fprintf(sp,"/* Write fitness function for %s here. */\n",Pops[i].Name);
  1648.         }
  1649.         fprintf(sp,"return(fitness);\n}\n\n");
  1650.     } else {
  1651.         struct stat State;
  1652.         if(stat(Pops[i].FFile,&State)==0) {
  1653.             char    *tbuf;
  1654.             tbuf = malloc(State.st_size+1);
  1655.             if(tbuf!=0) {
  1656.                 FILE *ffp;
  1657.                 ffp = fopen(Pops[i].FFile,"rb");
  1658.                 if(ffp!=0) {
  1659.                     fread(tbuf,State.st_size,1,ffp);
  1660.                     fclose(ffp);
  1661.                     tbuf[State.st_size]=0;
  1662.                     filtdump(sp,tbuf,i);
  1663.                     free(tbuf);
  1664.                 } else {
  1665.                     msg("Unable to read fitness file, skipping... [ENTER]");
  1666.                 }
  1667.             } else {
  1668.                 msg("Infernal error, virtual store exhausted. malloc() failed. [ENTER]");
  1669.             }
  1670.         } else {
  1671.             msg("Unable to load external fitness function, defaulting to empty function.\n[ENTER]");
  1672.             fprintf(sp,"double %sFitness(struct %s *Polly)\n{\ndouble fitness=0.0;\n",Pops[i].Name,Pops[i].Name);
  1673.             if(Project.CLevel>0) {
  1674.                 fprintf(sp,"/* Write fitness function for %s here. */\n",Pops[i].Name);
  1675.             }
  1676.             fprintf(sp,"return(fitness);\n}\n\n");
  1677.         }
  1678.     }
  1679. }
  1680.  
  1681.  
  1682. if(Project.CLevel>0) {
  1683.     fprintf(fp,"/*=== Crossover, Mutation etc. functions. ===*/\n\n");
  1684. }
  1685.  
  1686. /* Functions */
  1687.  
  1688. for(i=0;i!=Project.NumPops;i++) {
  1689.     switch(Pops[i].Type) {
  1690.     case    PTYPE_Bitstring:
  1691.         filtdump(fp,Bitstring_c,i);
  1692.     break;
  1693.  
  1694.     case PTYPE_Bitmatrix:
  1695.         filtdump(fp,Bitmatrix_c,i);
  1696.     break;
  1697.  
  1698.     case PTYPE_BRVector:
  1699.         filtdump(fp,BRVector_c,i);
  1700.     break;
  1701.  
  1702.     case PTYPE_Custom:
  1703.         filtdump(fp,Skeleton_c,i);
  1704.     break;
  1705.  
  1706.     }
  1707. }
  1708.  
  1709. /* == magic == */
  1710.  
  1711.     if(Project.CLevel>0) {
  1712.         fprintf(fp,"\n/* vi: set ts=3: */ /* vim magic */\n");
  1713.     }
  1714.  
  1715.     fclose(fp);
  1716.     if(fp!=sp) {
  1717.         fclose(sp);
  1718.     }
  1719.     if(fp!=hp) {
  1720.         fclose(hp);
  1721.     }
  1722.  
  1723.  
  1724. /* Report files. */
  1725.  
  1726. if(rep!=0) {
  1727.     strcpy(buf,dstdir);
  1728.     addpart(buf,"report.h");
  1729.     if(file_write(buf)) {
  1730.         if((fp=fopen(buf,"wb"))!=NULL) {
  1731.             fwrite(report_h,report_h_SIZE,1,fp);
  1732.             fclose(fp);
  1733.         }
  1734.     }
  1735.  
  1736.     strcpy(buf,dstdir);
  1737.     addpart(buf,"report.c");
  1738.     if(file_write(buf)) {
  1739.         if((fp=fopen(buf,"wb"))!=NULL) {
  1740.             fwrite(report_c,report_c_SIZE,1,fp);
  1741.             fclose(fp);
  1742.         }    
  1743.     }
  1744. }
  1745.  
  1746.  
  1747. /* Makefile */
  1748.  
  1749. strcpy(buf,dstdir);
  1750. addpart(buf,"Makefile");
  1751. if(file_write(buf)) {
  1752.     if((fp=fopen(buf,"wb"))!=NULL) {
  1753.         filtdump(fp,mk,0);
  1754.         fclose(fp);
  1755.     }
  1756. }
  1757.  
  1758. /* PostScript(tm) generation script */
  1759.  
  1760. if(Project.flags&WIZFLG_PSPLOT) {
  1761.     strcpy(buf,dstdir);
  1762.     addpart(buf,"MakePS");
  1763.     if(file_write(buf)) {
  1764.         if((fp=fopen(buf,"wb"))!=NULL) {
  1765.             fprintf(fp,"\n# PostScript(tm) generation script for GNUPlot.\n# Created by the GAP Conjurer.\n\n");
  1766.             fprintf(fp,"set terminal postscript landscape monochrome\n\n");
  1767.             for(i=0;i!=Project.NumPops;i++) {
  1768.                 for(n=0;n!=6;n++) {
  1769.                     if(Pops[i].RFlags[n]!=0) {
  1770.                         fprintf(fp,"set output \"%s%s.ps\"\n",Pops[i].Name,RepDefs[n]);
  1771.                         fprintf(fp,"set title \"%s %s\"\n",Pops[i].Name,RepNames[n]);
  1772.                         fprintf(fp,"plot \"%s.%s\" with lines\n\n",Pops[i].Name,RepExts[n]);
  1773.                     }
  1774.                 }
  1775.             }
  1776.             fclose(fp);
  1777.         }
  1778.     }
  1779. }
  1780.  
  1781. if(Project.flags&WIZFLG_PLOT) {
  1782.     strcpy(buf,dstdir);
  1783.     addpart(buf,"ShowReport");
  1784.     if(file_write(buf)) {
  1785.         if((fp=fopen(buf,"wb"))!=NULL) {
  1786.             fprintf(fp,"\n# Report display script for GNUPlot.\n# Generated by the GAP Conjurer.\n\n");
  1787.             buf[0] = 0;
  1788.             for(i=0;i!=Project.NumPops;i++) {
  1789.                 for(n=0;n!=6;n++) {
  1790.                     if(Pops[i].RFlags[n]!=0) {
  1791.                         sprintf(&buf[strlen(buf)],"\t\"%s.%s\" with lines,\\\n",Pops[i].Name,RepExts[n]);
  1792.                     }
  1793.                 }
  1794.             }
  1795.             buf[strlen(buf)-3] = 0;
  1796.             fprintf(fp,"plot \\\n%s",buf);
  1797.             fprintf(fp,"\npause -1 \"Press enter to continue...\"");
  1798.             fclose(fp);
  1799.         }
  1800.     }
  1801. }
  1802.  
  1803.     sprintf(MOTD,"Created the %s project.",Project.Name);
  1804.  
  1805. } else {
  1806.     strcpy(MOTD,"Error creating project.");
  1807.     msg("create_project: Unable to open file for writing. [ENTER]");
  1808. }
  1809.  
  1810. free(buf);
  1811.  
  1812. return;
  1813. }
  1814.  
  1815. char *addpart(char *buf,char *fname)
  1816. {
  1817. int l;
  1818.  
  1819. l = strlen(buf);
  1820.  
  1821. #ifdef    AMIGA
  1822. if(buf[l-1]==DIR_SEPARATOR || buf[l-1]==':' || buf[0]==0) {
  1823. #else
  1824. if(buf[l-1]==DIR_SEPARATOR || buf[0]==0) {
  1825. #endif
  1826.     strcat(buf,fname);
  1827. } else {
  1828.     buf[l]=DIR_SEPARATOR;
  1829.     buf[l+1]=0;
  1830.     strcat(buf,fname);
  1831. }
  1832. return(buf);
  1833. }
  1834.  
  1835. void filtdump2(FILE *fp,char *data,int indx,int v)
  1836. {
  1837. int n;
  1838. int z;
  1839. static int p;
  1840.  
  1841. if(fp==NULL) {
  1842.     p= -1;
  1843.     return;
  1844. }
  1845.  
  1846. while((z=data[++p])!=0) {
  1847.     if(z=='$') {
  1848.         z=data[++p];
  1849.         switch(z) {
  1850.         case    '1':
  1851.         case    '2':
  1852.         case    '3':
  1853.         case    '4':
  1854.             n = z-'1';
  1855.             filtdump2(fp,data,indx,((Project.CLevel>n)?1:0)&v);
  1856.         break;
  1857.  
  1858.         case    'N':
  1859.             if(v){fprintf(fp,Project.Pops[indx].Name);}
  1860.         break;
  1861.  
  1862.         case    'I':
  1863.             if(v){fprintf(fp,"%d",indx);}
  1864.         break;        
  1865.  
  1866.         case    '$':
  1867.             if(v){fputc('$',fp);}
  1868.         break;
  1869.  
  1870.         case    'P':
  1871.             if(v){fprintf(fp,Project.Name);}
  1872.         break;
  1873.  
  1874.         case    'U':
  1875.             filtdump2(fp,data,indx,((Project.sep)?1:0)&v);
  1876.         break;
  1877.  
  1878.         case    'R':
  1879.             filtdump2(fp,data,indx,((Project.rep)?1:0)&v);
  1880.         break;
  1881.  
  1882.         default:
  1883.             p--;
  1884.             return;        
  1885.         }
  1886.     } else if(v!=0) {
  1887.         fputc(z,fp);
  1888.     }
  1889. }
  1890.  
  1891. }
  1892.  
  1893.  
  1894. void filtdump(FILE *fp,unsigned char *data,int indx)
  1895. {
  1896.  
  1897. filtdump2(0,0,0,0);
  1898. filtdump2(fp,data,indx,1);
  1899.  
  1900. }
  1901.  
  1902. int file_write(char *fname)
  1903. {
  1904. int    r,i=0;
  1905. struct stat State;
  1906. char    buf[255];
  1907.  
  1908. r=stat(fname,&State);
  1909.  
  1910. if(r==0) {
  1911.     sprintf(buf,"%s exists, overwrite? " DEFN " : ",fname);
  1912.     if(bool_query(buf,NO)) {
  1913.         i = 1;
  1914.     }
  1915. } else {
  1916.     switch(errno) {
  1917.  
  1918.     case    ENOENT:
  1919.         i = 1;
  1920.     break;
  1921.  
  1922.     case    EBUSY:
  1923.         msg("File already in use. [ENTER]");
  1924.         i = 0;
  1925.     break;
  1926.  
  1927.     case    EPERM:
  1928.         msg("Access denied. [ENTER]");
  1929.         i = 0;
  1930.     break;
  1931.  
  1932.     default:
  1933.         sprintf(buf,"Unexpected forseen but unknown error on file \"%s\". [ENTER]",fname);
  1934.         msg(buf);
  1935.         i = 0;
  1936.     }
  1937. }
  1938.  
  1939. return(i);
  1940. }
  1941.  
  1942.